import { Component, OnDestroy, OnInit, ViewChild, EventEmitter } from '@angular/core';
import { MatPaginator, MatSort } from '@angular/material';
import { merge, of as observableOf } from 'rxjs';
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { MatDialog } from '@angular/material';
import { RestService } from '../services/rest.service';
import { TranslateService } from '@ngx-translate/core';
import { DeviceDialogComponent } from './device-dialog/device-dialog.component';
import { FindDeviceComponent } from './find-device/find-device.component';
import { SuimageComponent } from './suimage/suimage.component';
import { DialogTypes, ActionTypes } from '../models/wdl-types';

import * as _ from 'lodash';

@Component({
  templateUrl: './device.component.html',
  styleUrls: ['./device.component.css'],
})
export class DeviceComponent implements OnInit, OnDestroy {
  url = 'data/device';
  institution: any;
  user: any;
  displayedColumns: string[] = ['number', 'deviceId', 'deviceType', 'personName', 'updateTime', 'actions'];
  dataSource = [];
  deviceType = '00';
  searchText = '';

  resultsLength = 0;
  pageSize = 25;
  isLoadingResults = true;

  search: EventEmitter<any> = new EventEmitter();
  uploadConfig: any;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor(public dialog: MatDialog,
              private router: Router,
              private translate: TranslateService,
              private rest: RestService) {
    this.institution = this.rest.getInstitution();
    if (!this.institution.id) {
      console.error('Instituion is invalid: ' + this.institution.id);
    }
    this.user = this.rest.getUser();
    if (!this.isUserQualified()) {
      this.displayedColumns = ['deviceId', 'deviceType', 'personName', 'updateTime'];
    }

  }

  isUserQualified() {
    return this.user.role === 'header';
  }

  isUserQualified4find() {
    // only hushitong header is qualified
    return (this.institution.instName === '护适通') && this.user.role === 'header';
  }

  refreshSearch() {
    this.paginator.pageIndex = 0;
    this.search.emit(this.searchText);
  }

  deviceTypeChanges(event) {
    this.deviceType = event.value;
    this.refreshSearch();
  }

  add() {
    this.dialog.open(DeviceDialogComponent, {
      disableClose: false,
      autoFocus: true,
      width: '450px',
      data: {
        mode: ActionTypes.ADD
      }
    }).afterClosed().subscribe(data => {
      if (!data || _.isString(data)) {
        // action was aborted
        return;
      }

      this.rest.post(this.url, data).subscribe((resp) => {
        console.log('Device' + data.deviceId + ' was added.');
        // link it to institution
        this.rest.link(this.url + '/' + resp['id'] + '/institution', 'data/institution/' + this.institution.id).subscribe(() => {
          this.refreshSearch();
        }, () => {
          console.error('Failed to link device to institution');
          this.refreshSearch();
        });
      }, message => {
        this.rest.showHttpError('addInstError', message);
      });
    });
  }

  find() {
    this.dialog.open(FindDeviceComponent, {
      disableClose: false,
      autoFocus: true,
      width: '450px',
      data: {
        mode: ActionTypes.ADD
      }
    });
  }

  checkAndUpload() {
    this.dialog.open(SuimageComponent, {
      disableClose: false,
      autoFocus: true,
      width: '800px'
    });
  }

  remove(device) {
    // check if the device is used by somebody
    if (device.personName) {
      const nonEmptyTitle = this.translate.get('deleteError')['value'];
      this.rest.openGenDialog(
        DialogTypes.ERROR,
        nonEmptyTitle,
        this.translate.get('nonEmptyDeviceMessage', {personName: device.personName})['value'],
        null);
      return;
    }

    const title = this.translate.get('deleteConfirmation')['value'];
    const message = this.translate.get('deleteDeviceMessage', {deviceId: device.deviceId})['value'];

    this.rest.openGenDialog(DialogTypes.CONFIRMATION, title, message, () => {
      this.rest.delete(this.url + '/' + device.id).subscribe(() => {
        this.refreshSearch();
      }, error => {
        this.rest.showHttpError(this.translate.get('error')['value'], error);
      });
    });
  }

  ngOnInit() {
    // If the user changes the sort order, reset back to the first page.
    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);

    merge(this.sort.sortChange, this.paginator.page, this.search)
    .pipe(
      startWith({}),
      switchMap(() => {
        this.isLoadingResults = true;

        const params = {
          institutionId: this.institution.id,
          page: this.paginator.pageIndex ? this.paginator.pageIndex : 0,
          size: this.paginator.pageSize ? this.paginator.pageSize : this.pageSize
        };

        if (this.sort.active && this.sort.direction) {
          params['sort'] = this.sort.active + ',' + this.sort.direction
        }

        if (this.deviceType === '00') {
          if (this.searchText) {
            params['deviceId'] = this.searchText;
            return this.rest.getWithParams(this.url + '/search/deviceIds', params);
          } else {
            return this.rest.getWithParams(this.url + '/search/all', params);
          }
        } else {
          params['deviceType'] = this.deviceType + '%';
          if (this.searchText) {
            params['deviceId'] = '%' + this.searchText + '%';
            return this.rest.getWithParams(this.url + '/search/deviceTypeIds', params);
          } else {
            return this.rest.getWithParams(this.url + '/search/allTypes', params);
          }
        }
      }),
      map(data => {
        this.isLoadingResults = false;
        this.resultsLength = data['page']['totalElements'];
        const devices = data['_embedded']['devices'];

        let number = this.paginator.pageIndex * this.paginator.pageSize;
        devices.forEach(device => {
          device['number'] = ++number;
          device['deviceType'] = 'device' + device.deviceId.substring(0, 2);
        });

        return devices;
      }),
      catchError(() => {
        this.isLoadingResults = false;
        return observableOf([]);
      })
    ).subscribe(data => this.dataSource = data);
  }

  ngOnDestroy() {
  }
}
